package org.filetransfer.file_transfer_java_backend.service;
import jakarta.annotation.Nullable;
import org.filetransfer.file_transfer_java_backend.controller.ShareItemController;
import org.filetransfer.file_transfer_java_backend.entity.File;
import org.filetransfer.file_transfer_java_backend.entity.ShareItem;
import org.filetransfer.file_transfer_java_backend.entity.User;
import org.filetransfer.file_transfer_java_backend.model.ServiceShareInfoModel;
import org.filetransfer.file_transfer_java_backend.repository.ShareItemRepository;
import org.filetransfer.file_transfer_java_backend.repository.UserRepository;
import org.filetransfer.file_transfer_java_backend.utils.PickupCodeGenerator;
import org.hibernate.Hibernate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@Service
@Transactional
public class ShareItemService {
    @Autowired
    private ShareItemRepository shareItemRepository;
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private FileUploadService fileUploadService;
    public ShareItem getShareItemById(Long id) {
        return shareItemRepository.findById(id).orElseThrow(() -> new RuntimeException("分享项未找到"));
    }
    private String generateUniqueShareItem() {
        String code;
        do {
            code = PickupCodeGenerator.generateCode();
        } while (shareItemRepository.existsByCode(code));
        return code;
    }
    public void deleteShare(String code, String editToken) {
        var shareItem = shareItemRepository.findByCode(code).orElseThrow(() -> new RuntimeException("分享项未找到"));
        verifyEditTokenOrThrow(shareItem, editToken);
        shareItemRepository.delete(shareItem);
    }
    public void verifyEditTokenOrThrow(ShareItem shareItem, String editToken) {
        if (!editToken.equals(shareItem.getEditToken())) {
            throw new RuntimeException("无效的编辑令牌");
        }
    }
    public void incrementDownloadCount(String code, String md5) {
        var shareItemOptional = shareItemRepository.findByCode(code);
        if (shareItemOptional.isEmpty()) {
            throw new RuntimeException("分享项未找到");
        }
        var shareItem = shareItemOptional.get();
        var fileOptional = shareItem.getFiles().stream().filter(file -> file.getMd5().equals(md5)).findFirst();
        if (fileOptional.isEmpty()) {
            throw new RuntimeException("文件未找到");
        }
        var file = fileOptional.get();
        file.setDownloadCount(file.getDownloadCount() + 1);// 下载次数+1
        shareItemRepository.save(shareItem);
    }
    public record ShareItemInfoResult(ShareItem shareItem, String editToken) {}
    public ShareItemInfoResult createShareItem(ShareItemController.NewShareItemInfo info) {
        var code = generateUniqueShareItem();
        String dir = fileUploadService.getUploadFilePath(code);
        var files = fileUploadService.moveFilesToStorage(info.files(), dir);
        // 获取当前用户，如果未登录则使用游客用户
        User currentUser = getCurrentUserOrGuest();
        ShareItem shareItem = ShareItem.builder()
                .files(files)
                .code(code)
                .user(currentUser)
                .build();
        for (File file : files) {
            file.setShareItem(shareItem);
        }
        var editToken = UUID.randomUUID().toString();
        shareItem.setEditToken(editToken);
        //TODO: shareItem.setExpiryTime(info.expiryTime());
        // 设置过期时间
        // 保存分享项
        shareItemRepository.save(shareItem);
        // 编辑token，随机生成
        return new ShareItemInfoResult(shareItem, editToken);
    }
    public Optional<ShareItem> getShareItem(String code) {
        var itemOptional = shareItemRepository.findByCode(code);
        if (itemOptional.isEmpty()) {
            return Optional.empty();
        }
        var item = itemOptional.get();
        // 提前加载关联对象，避免出事务再获取报错
        Hibernate.initialize(item.getFiles());
        Hibernate.initialize(item.getMessages());
        return Optional.of(item);
    }
    public Optional<File> getShareItemFile(String code, String md5) {
        return shareItemRepository.findByCode(code).flatMap(shareItem -> shareItem.getFiles().stream().filter(file -> file.getMd5().equals(md5)).findFirst());
    }
    public Optional<ServiceShareInfoModel> getStatistics(@Nullable Integer dayOfBefore) {
        if (dayOfBefore == null) {
            return shareItemRepository.getStatistics();
        }
        var now = Instant.now();
        var end = now.minusSeconds(dayOfBefore * 24 * 60 * 60);
        var start = end.minusSeconds(24 * 60 * 60);
        return shareItemRepository.getStatisticsInRange(start, end);
    }
    public Optional<ServiceShareInfoModel> getStatisticsByUser(@Nullable Integer dayOfBefore, Long userId) {
        if (dayOfBefore == null) {
            return shareItemRepository.getStatisticsByUser(userId);
        }
        var now = Instant.now();
        var end = now.minusSeconds(dayOfBefore * 24 * 60 * 60);
        var start = end.minusSeconds(24 * 60 * 60);
        return shareItemRepository.getStatisticsInRangeByUser(start, end, userId);
    }
    /**
     * 获取当前登录用户的分享列表
     */
    public List<ShareItem> getCurrentUserShares() {
        User currentUser = getCurrentUser();
        var shares = shareItemRepository.findByUserIdOrderByCreateTimeDesc(currentUser.getId());
        // 预加载关联对象，避免延迟加载问题
        for (ShareItem share : shares) {
            Hibernate.initialize(share.getFiles());
            Hibernate.initialize(share.getMessages());
        }
        return shares;
    }
    /**
     * 获取当前登录用户，如果未登录抛出异常
     */
    private User getCurrentUser() {
        var authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null && authentication.isAuthenticated()
                && !"anonymousUser".equals(authentication.getPrincipal())
                && authentication.getPrincipal() instanceof User) {
            return (User) authentication.getPrincipal();
        }
        throw new RuntimeException("用户未登录，请先登录");
    }
    /**
     * 获取当前用户，如果未登录则返回游客用户
     */
    private User getCurrentUserOrGuest() {
        try {
            var authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication != null && authentication.isAuthenticated()
                    && !"anonymousUser".equals(authentication.getPrincipal())
                    && authentication.getPrincipal() instanceof User) {
                return (User) authentication.getPrincipal();
            }
        } catch (Exception e) {
            // 忽略异常，返回游客用户
        }
        // 返回或创建游客用户
        return getOrCreateGuestUser();
    }
    /**
     * 获取或创建游客用户
     */
    private User getOrCreateGuestUser() {
        return userRepository.findByUsername("guest")
                .orElseThrow(() -> new RuntimeException("游客用户未初始化，请联系管理员"));
    }
}
